unit TaskList;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,ComCtrls, ExtCtrls, StdCtrls,
  wsMain,wsClasses,wsDB,wsControls,wsDiagram, atDiagram, LiveDiagram, Menus;

type
  TFormTaskList = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    WorkflowDiagram1: TWorkflowDiagram;
    TabSheet2: TTabSheet;
    lvTasks: TTaskListView;
    Timer1: TTimer;
    PopupMenu1: TPopupMenu;
    miView: TMenuItem;
    Showonlyopentasks2: TMenuItem;
    Showalltasks2: TMenuItem;
    PopupMenu2: TPopupMenu;
    N1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure lvTasksCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure lvTasksSelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);
    procedure Timer1Timer(Sender: TObject);
    procedure WorkflowDiagram1Click(Sender: TObject);
    procedure miViewClick(Sender: TObject);
    procedure Showalltasks2Click(Sender: TObject);
    procedure N1Click(Sender: TObject);
  private
    { Private declarations }
    FWorkIns: TWorkflowInstance;
    FLastActivePageName: string;
    FUpdatingTabs: integer;
    FFieldPanel: TTaskFieldPanel;
    FLogView: TTaskLogListView;
    FFreeOnClose: boolean;
    FWorkflowStudio: TWorkflowStudio;
    FOldRunFinished: TWorkflowInstanceEvent;

    procedure RunFinished(Sender: TObject; AWorkIns: TWorkflowInstance);
   procedure UpdateWorkflowDiagram;
   function GetWorkIns: TWorkflowInstance;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent; AWorkflowStudio: TWorkflowStudio); reintroduce;
    destructor Destroy; override;

    procedure LoadData;
    procedure SetFilter(FilterType: TTaskFilterType; AFilter: string);
    procedure SaveChanges;

    property WorkflowInstance : TWorkflowInstance read GetWorkIns;
  end;

var
  FormTaskList: TFormTaskList;

implementation
uses wsRes;
{$R *.dfm}

constructor TFormTaskList.Create(AOwner: TComponent;
  AWorkflowStudio: TWorkflowStudio);
begin
  inherited Create(AOwner);
  if AWorkflowStudio <> nil then
    FWorkflowStudio := AWorkflowStudio
  else
    raise Exception.CreateFmt('WorkflowStudio parameter not specified in %s.Create.', [ClassName]);

  WorkflowDiagram1.WorkflowStudio := FWorkflowStudio;
  lvTasks.WorkflowStudio := FWorkflowStudio;
  FOldRunFinished := FWorkflowStudio.OnRunFinished;
  FWorkflowStudio.OnRunFinished := RunFinished;
end;

destructor TFormTaskList.Destroy;
begin
  FWorkflowStudio.OnRunFinished := FOldRunFinished;
  inherited;
end;

procedure TFormTaskList.FormCreate(Sender: TObject);
begin
{  //frTaskView.OnTaskChanged := TaskEdited;
  FFieldPanel := TTaskFieldPanel.Create(Self);
  FFieldPanel.Parent := TabControl1;
  FFieldPanel.Align := alClient;

  FLogView := TTaskLogListView.Create(Self);
  FLogView.WorkflowStudio := FWorkflowStudio;
  FLogView.Parent := TabControl1;
  FLogView.Align := alClient;

  FUpdatingTabs := 0;
  frTaskView.Task := nil;
}

  {Create list view columns}
  lvTasks.Columns.Clear;
  With lvTasks.Columns.Add do
  begin
    Caption := _str(SColumnKey);
    Width := 40;
  end;
  With lvTasks.Columns.Add do
  begin
    Caption := _str(SColumnName);
    Width := 100;
  end;
  With lvTasks.Columns.Add do
  begin
    Caption := _str(SColumnWorkflow);
    Width := 100;
  end;
  With lvTasks.Columns.Add do
  begin
    Caption := _str(SColumnSubject);
    Width := 220;
  end;
  With lvTasks.Columns.Add do
  begin
    Caption := _str(SColumnStatus);
    Width := 100;
  end;
  With lvTasks.Columns.Add do
  begin
    Caption := _str(SColumnUser);
    Width := 100;
  end;

end;

procedure TFormTaskList.LoadData;
begin
  lvTasks.LoadFromDatabase;
  if lvTasks.SelectedTask = nil then
  begin
    if lvTasks.Items.Count > 0 then
      lvTasks.Items.Item[0].Selected := true
    else
      lvTasksSelectItem(nil, nil, false);
  end;
end;

procedure TFormTaskList.RunFinished(Sender: TObject;
  AWorkIns: TWorkflowInstance);
begin
  LoadData;
  if Assigned(FOldRunFinished) then
    FOldRunFinished(Sender, AWorkIns);
end;

procedure TFormTaskList.SetFilter(FilterType: TTaskFilterType;
  AFilter: string);
begin
  lvTasks.FilterType := FilterType;
  lvTasks.FilterKey := AFilter;
end;

procedure TFormTaskList.FormShow(Sender: TObject);
begin
  UpdateWorkflowDiagram;

end;

procedure TFormTaskList.UpdateWorkflowDiagram;
var
  AWorkIns: TWorkflowInstance;
begin
  if (lvTasks.SelectedTask <> nil) or (lvTasks.FilterType = tfWorkIns) then
  begin
    WorkflowDiagram1.BeginUpdate;
    try
      AWorkIns := GetWorkIns;
      AWorkIns.AssignToDiagram(WorkflowDiagram1, true);
      WorkflowDiagram1.DisplayTaskStatus := true;

      Case AWorkIns.Status of
        wsNotStarted:
          WorkflowDiagram1.ViewStateMode := vmStart;
        wsFinished, wsFinishedWithError:
          WorkflowDiagram1.ViewStateMode := vmEnd;
      else
          WorkflowDiagram1.ViewStateMode := vmRun;
      end;

      WorkflowDiagram1.TopRuler.Visible := false;
      WorkflowDiagram1.LeftRuler.Visible := false;
      WorkflowDiagram1.AutoPage := false;
      WorkflowDiagram1.AutoScroll := true;
      WorkflowDiagram1.PageLines.Visible := false;
      WorkflowDiagram1.State := dsView;
      WorkflowDiagram1.MakeActiveNodeVisible;
    finally
      WorkflowDiagram1.EndUpdate;
    end;
  end
  else
    WorkflowDiagram1.Clear;

end;

function TFormTaskList.GetWorkIns: TWorkflowInstance;
begin
  {Check if WorkIns is already loaded}
  if FWorkIns <> nil then
  begin
    case lvTasks.FilterType of
      tfWorkIns:
        if FWorkIns.Key = lvTasks.FilterKey then
        begin
          result := FWorkIns;
          exit;
        end;
    else
      begin
        if (lvTasks.SelectedTask <> nil) and (FWorkIns.Key = lvTasks.SelectedTask.WorkInsKey) then
        begin
          result := FWorkIns;
          exit;
        end;
      end;
    end;
  end;

  {FWorkIns must be reloaded}
  if FWorkIns <> nil then
    FWorkIns.Free;

  FWorkIns := TWorkflowInstance.Create(nil, FWorkflowStudio);
  if lvTasks.FilterType = tfWorkIns then
    FWorkIns.Key := lvTasks.FilterKey {workInskey}
  else
    if lvTasks.SelectedTask <> nil then
      FWorkIns.Key := lvTasks.SelectedTask.WorkInsKey
    else
    begin
      FWorkIns.Free;
      FWorkIns := nil;
    end;

  FWorkflowStudio.WorkflowManager.LoadWorkflowInstance(FWorkIns);
  result := FWorkIns;
end;

procedure TFormTaskList.lvTasksCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  ATask: TTaskInstance;
begin
  ATask := nil;
  if Item <> nil then
    ATask := lvTasks.TaskFromItem(Item);
  if ATask <> nil then
  begin
    if ATask.Completed then
      lvTasks.Canvas.Font.Color := clGray;
  end;
  DefaultDraw := true;

end;

procedure TFormTaskList.lvTasksSelectItem(Sender: TObject; Item: TListItem;
  Selected: Boolean);
begin
  Timer1.Enabled := false;
  Timer1.Enabled := true;
end;

procedure TFormTaskList.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := false;
  if (not (csDestroying in ComponentState)) then
  begin
      UpdateWorkflowDiagram;
(*    {Save last active page name}
    if TabControl1.TabIndex > -1 then
      FLastActivePageName := TabControl1.Tabs[TabControl1.TabIndex];

    BeginUpdateTabs;
    try
      frTaskView.Task := lvTasks.SelectedTask;
      if lvTasks.SelectedTask <> nil then
        frTaskView.ExpirationDateTime := FWorkflowStudio.TaskManager.TaskExpirationDateTime(GetWorkIns, lvTasks.SelectedTask)
      else
        frTaskView.ExpirationDateTime := 0;

      UpdateWorkflowDiagram;
      UpdateAttachmentTabs;

      {The following methods *must* be called in that order}
      UpdateFixedTabs;
      UpdateFieldsTab;
      UpdateLogTab;

      if lvTasks.SelectedTask <> nil then
      begin
        {Recover the active page}
        TabControl1.TabIndex := TabControl1.Tabs.IndexOf(FLastActivePageName);
      end;
      btSaveChanges.Enabled := (lvTasks.SelectedTask <> nil) and not lvTasks.SelectedTask.Completed
        and lvTasks.SelectedTask.CanUpdate(FWorkflowStudio.UserManager.LoggedUserId, FWorkflowStudio);

    finally
      EndUpdateTabs;
    end;

    UpdateActivePage;
    *)
  end;

end;

procedure TFormTaskList.WorkflowDiagram1Click(Sender: TObject);
begin
  WorkflowDiagram1.SetFocus;
end;

procedure TFormTaskList.SaveChanges;
var
  AAttach: TWorkflowAttachment;
  AWorkIns: TWorkflowInstance;
  lvItems: TAttachmentListView;
  c: integer;
  WorkflowVar: TWorkflowVariable;
begin
  if lvTasks.SelectedTask <> nil then
  begin
    {Get the workflowinstance related to the task. Be sure to refresh the workflow instance}
    if FWorkIns <> nil then
    begin
      FWorkIns.Free;
      FWorkIns := nil;
    end;
    AWorkIns := GetWorkIns;

  (*  {Save the attachments}
    {$WARNINGS OFF}
    for c := 0 to TabControl1.Tabs.Count - 1 do if integer(TabControl1.Tabs.Objects[c]) > _MaxFixedTab then
    {$WARNINGS ON}
    begin
      AAttach := AWorkIns.Diagram.Attachments.FindByName(TabControl1.Tabs[c]);
      if AAttach <> nil then
      begin
        lvItems := TfrAttachmentFrame(TabControl1.Tabs.Objects[c]).lvItems;
        if lvItems <> nil then
        begin
          AAttach.Items.WorkflowStudio := lvItems.Attachments.WorkflowStudio;
          AAttach.Items.Assign(lvItems.Attachments);
        end;
      end;
    end;
  *)

    if lvTasks.SelectedTask.UserID = '101' then
    begin
      WorkflowVar := AWorkIns.Diagram.Variables.FindByName('JE');
      if WorkflowVar <> nil then
        WorkflowVar.Value := 200;
    end;

  (*
    {Save the fields}
    if FindTabByType(_FieldTabIndex) > -1 then
    begin
      if not FFieldPanel.ValidateValues then
      begin
        TabControl1.TabIndex := FindTabByType(_FieldTabIndex);
        TabControl1Change(TabControl1);
        if FFieldPanel.CanFocus then
          FFieldPanel.SetFocus;
        FFieldPanel.FocusLastError;
        ShowMessage(FFieldPanel.ErrorInfo.Msg);
        Abort;
        //raise EWorkflowException.Create(FFieldPanel.ErrorInfo.Msg);
      end;                                              
      FFieldPanel.SaveDiagramVariables(AWorkIns.Diagram);
    end;
   *)
    {Save the workflow instance}
    FWorkflowStudio.WorkflowManager.SaveWorkflowInstance(AWorkIns);

    {Save the task instance. WARNING - this should be done after any saving code, because
     it loads the workflowinstance and signal it (run it again). So, it must be executed
     after all processing so it gets the most up to date workflow instance object}
    FWorkflowStudio.TaskManager.SaveTaskInstance(lvTasks.SelectedTask);

    {From below, it's only visual stuff}                      

    {Reload the task list from database, in case it's not more in the list (for example,
     it might be completed}
//    FTimer.Enabled := True;
    LoadData;
    //lvTasks.LoadFromDatabase;
  end;

end;

procedure TFormTaskList.miViewClick(Sender: TObject);
begin
  lvTasks.OnlyCompleted := true;
  LoadData;
end;

procedure TFormTaskList.Showalltasks2Click(Sender: TObject);
begin
  lvTasks.OnlyCompleted := false;
  LoadData;
end;

procedure TFormTaskList.N1Click(Sender: TObject);
begin
//  WorkflowDiagram1.ExportAsBMP('c:\wfdiagrm.bmp');
  WorkflowDiagram1.CopyBitmapToClipboard;
end;

end.
